{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# yield 协程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "def A():\n",
    "    while 1:\n",
    "        print('----A-----')\n",
    "        time.sleep(0.5)\n",
    "        yield 1\n",
    "\n",
    "def B():\n",
    "    while 1:\n",
    "        print('----B-----')\n",
    "        time.sleep(0.5)\n",
    "        next(a)\n",
    "\n",
    "a = A()\n",
    "\n",
    "B()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 斐波那契数列\n",
    "\n",
    "def fib(max):\n",
    "    n, a, b = 0, 0, 1\n",
    "    while n < max:\n",
    "        yield b   # 这种一边循环一边计算的机制，节省了存储空间，提高了运行效率。\n",
    "        a, b = b, a + b\n",
    "        n = n + 1\n",
    "        \n",
    "list(fib(10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# greenlet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from greenlet import greenlet\n",
    "import time\n",
    "\n",
    "def A():\n",
    "    while 1:\n",
    "        print('-------A-------')\n",
    "        time.sleep(0.5)\n",
    "        g2.switch()\n",
    "\n",
    "def B():\n",
    "    while 1:\n",
    "        print('-------B-------')\n",
    "        time.sleep(0.5)\n",
    "        g1.switch()\n",
    "\n",
    "g1 = greenlet(A)  #创建协程g1\n",
    "g2 = greenlet(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------A-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-2-6e07d0b81c73>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mswitch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m#跳转至协程g1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-1-02d48124e0c9>\u001b[0m in \u001b[0;36mB\u001b[0;34m()\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0;32mwhile\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'-------B-------'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m         \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     14\u001b[0m         \u001b[0mg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mswitch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     15\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "g1.switch()  #跳转至协程g1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. gevent\n",
    "\n",
    "greenlet可以实现协程，不过每一次都要人为的去指向下一个该执行的协程，显得太过麻烦。python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent\n",
    "gevent每次遇到io操作，需要耗时等待时，会自动跳到下一个协程继续执行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------A-------\n",
      "-------B-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------B-------\n",
      "-------A-------\n",
      "-------B-------\n",
      "-------B-------\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "KeyboardInterrupt\n",
      "2019-04-28T15:16:49Z\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-3-457c924cc68a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     13\u001b[0m \u001b[0mg1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgevent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspawn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 创建一个协程\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0mg2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgevent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspawn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mB\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0mg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m#等待协程执行结束\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     16\u001b[0m \u001b[0mg2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/__greenlet_primitives.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/__greenlet_primitives.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32msrc/gevent/__greenlet_primitives.pxd\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives._greenlet_switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "import gevent\n",
    "\n",
    "def A():\n",
    "    while 1:\n",
    "        print('-------A-------')\n",
    "        gevent.sleep(1) #用来模拟一个耗时操作，注意不是time模块中的sleep\n",
    "\n",
    "def B():\n",
    "    while 1:\n",
    "        print('-------B-------')\n",
    "        gevent.sleep(0.5)  #每当碰到耗时操作，会自动跳转至其他协程\n",
    "\n",
    "g1 = gevent.spawn(A) # 创建一个协程\n",
    "g2 = gevent.spawn(B)\n",
    "g1.join()  #等待协程执行结束\n",
    "g2.join()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.协程gevent完成回显服务器："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "KeyboardInterrupt\n",
      "2019-07-10T07:53:28Z\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-4-c9b08ff68709>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     29\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     30\u001b[0m \u001b[0mg1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgevent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspawn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc_accept\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0mg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/_greenlet.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent._greenlet.Greenlet.join\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/__greenlet_primitives.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.5/dist-packages/gevent/__greenlet_primitives.cpython-35m-x86_64-linux-gnu.so\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;32msrc/gevent/__greenlet_primitives.pxd\u001b[0m in \u001b[0;36mgevent.__greenlet_primitives._greenlet_switch\u001b[0;34m()\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "import gevent\n",
    "from gevent import monkey, socket\n",
    "\n",
    "monkey.patch_all()  #有IO才做时需要这一句\n",
    "\n",
    "s = socket.socket(2, 1)  #用的都是gevent模块中的socket,但用法一样\n",
    "s.setsockopt(1, 2, 1)\n",
    "s.bind(('', 8889))\n",
    "s.listen(1024)\n",
    "\n",
    "\n",
    "def func_accept():\n",
    "    while 1:\n",
    "        cs, userinfo = s.accept()\n",
    "        print('来了一个客户' + str(userinfo))\n",
    "        g = gevent.spawn(func_recv, cs)  #每当有用户连接,增加一条协程\n",
    "\n",
    "\n",
    "def func_recv(cs):\n",
    "    while 1:\n",
    "        recv_data = cs.recv(1024)\n",
    "        print(recv_data)  #程谁堵塞了,便会跳转至其他协程\n",
    "        if len(recv_data) > 0:\n",
    "            cs.send(recv_data)\n",
    "        else:\n",
    "            cs.close()\n",
    "            break\n",
    "\n",
    "\n",
    "g1 = gevent.spawn(func_accept)\n",
    "g1.join()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# asyncio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import asyncio\n",
    "\n",
    "async def compute(x, y):\n",
    "    print(\"Compute %s + %s ...\" % (x, y))\n",
    "    await asyncio.sleep(1.0)\n",
    "    return x + y\n",
    "\n",
    "async def print_sum(x, y):\n",
    "    result = await compute(x, y)\n",
    "    print(\"%s + %s = %s\" % (x, y, result))\n",
    "\n",
    "loop = asyncio.get_event_loop()\n",
    "loop.run_until_complete(print_sum(1, 2))\n",
    "loop.close()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
